#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
数字组合生成器程序
Digital Combination Generator Program

作者: Claude Code
功能: 从1-30的数字中选择候选池，生成所有可能的7个数字组合，并根据条件进行筛选
"""

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import itertools
import csv
from datetime import datetime
from typing import Tuple, List, Set, Dict, Callable, Optional
from functools import partial


# ==================== 配置常量 ====================
class Config:
    """应用配置常量"""
    MIN_NUMBER = 1
    MAX_NUMBER = 30
    MIN_SELECTION = 7
    MAX_SELECTION = 15
    COMBO_SIZE = 7
    ANY_OPTION_INDEX = 0

    # 窗口配置
    WINDOW_GEOMETRY = "1300x900"
    WINDOW_MIN_SIZE = (1200, 800)

    # 质数集合
    PRIME_NUMBERS = {1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29}

    # 颜色配置
    UNSELECTED_BG = '#E3F2FD'
    UNSELECTED_FG = '#1976D2'
    SELECTED_BG = '#FF5722'
    SELECTED_FG = '#FF0000'
    GROUP_B_BG = '#673AB7'
    GROUP_B_FG = '#FFFFFF'
    HOVER_BG = '#BBDEFB'

    # 字体配置
    FONT_FAMILY = '微软雅黑'
    BUTTON_FONT_UNSELECTED = (FONT_FAMILY, 11, 'bold')
    BUTTON_FONT_SELECTED = (FONT_FAMILY, 13, 'bold')

    # AB分组标签样式
    GROUP_A_LABEL = 'A'
    GROUP_B_LABEL = 'B'

    # 老板键配置
    BOSS_KEY_ENABLED = True
    BOSS_KEY_DEFAULT = 'F12'
    BOSS_KEY_DOUBLE_CLICK_THRESHOLD = 500  # 毫秒
    BOSS_KEY_FAKE_TITLE = "工作报告.docx"
    BOSS_KEY_FAKE_MODE = "document"  # document 或 terminal


# 筛选器配置数据
FILTER_CONFIGS = {
    'prime_ratio': {
        'label': '质合比:',
        'options': ["任意", "1:6", "2:5", "3:4", "4:3", "5:2", "6:1"],
        'width': 10,
        'height': 6
    },
    'odd_ratio': {
        'label': '奇偶比:',
        'options': ["任意", "0:7", "1:6", "2:5", "3:4", "4:3", "5:2", "6:1", "7:0"],
        'width': 10,
        'height': 9
    },
    'path_ratio': {
        'label': '012路比:',
        'options': ["任意", "0:0:7", "0:1:6", "0:2:5", "0:3:4", "0:4:3", "0:5:2", "0:6:1", "0:7:0",
                   "1:0:6", "1:1:5", "1:2:4", "1:3:3", "1:4:2", "1:5:1", "1:6:0",
                   "2:0:5", "2:1:4", "2:2:3", "2:3:2", "2:4:1", "2:5:0",
                   "3:0:4", "3:1:3", "3:2:2", "3:3:1", "3:4:0",
                   "4:0:3", "4:1:2", "4:2:1", "4:3:0",
                   "5:0:2", "5:1:1", "5:2:0",
                   "6:0:1", "6:1:0", "7:0:0"],
        'width': 10,
        'height': 9,
        'scrollbar': True
    },
    'consecutive': {
        'label': '连号段数:',
        'options': ["任意", "0组", "1组", "2组", "3组"],
        'width': 8,
        'height': 5,
        'scrollbar': True
    },
    'ab_ratio': {
        'label': 'AB比:',
        'options': ["任意", "0:7", "1:6", "2:5", "3:4", "4:3", "5:2", "6:1", "7:0"],
        'width': 10,
        'height': 9
    }
}


# 帮助文本（从方法中提取）
HELP_TEXT = """数字组合生成器使用说明

功能说明：
1. 数字选择：从1-30中选择7-15个数字作为候选池
2. AB分组：将选中的数字分为A、B两组
3. 条件筛选：设置质合比、奇偶比、012路比、AB比、和值范围、跨度范围、连号条件
4. 组合生成：生成所有符合条件的7个数字组合
5. 老板键：快速隐藏程序界面，显示伪装窗口（双击F12键激活）

操作步骤：
1. 左键点击数字按钮选择候选数字（7-15个，默认加入A组）
2. 右键点击已选数字可将其切换到B组或切换回A组
3. 在条件设置区选择筛选条件（可选）
4. 点击"生成组合"按钮生成结果
5. 可导出结果为TXT或CSV格式

老板键功能说明：
【快捷键】
- 默认按键：F12（可在设置中更改）
- 激活方式：快速双击F12键（500ms内）
- 退出方式：在伪装模式下再次双击F12键

【伪装界面】
- 工作文档模式：显示项目进度报告，看起来像在工作
- 命令行模式：显示Windows命令行界面，看起来在处理系统任务
- 窗口标题可在设置中自定义（默认为"工作报告.docx"）

【使用技巧】
- 右下角状态栏显示老板键状态和当前按键
- 可在"老板键设置"中自定义按键、伪装模式和窗口标题
- 第一次按下会显示提示，快速双击即可激活
- 所有用户选择和筛选条件在伪装模式下保持不变

筛选条件说明：
【质合比、奇偶比、012路比】
- 可多选，默认为"任意"
- Ctrl+点击选择多个比例
- 选择"任意"时表示不限制

【AB比】
- 设置从A组和B组各选多少个数字
- 例如"3:4"表示从A组选3个、从B组选4个
- 选中的数字默认属于A组（橙红色背景，左上角标记"A"）
- 右键点击已选数字可切换到B组（深紫色背景，左上角标记"B"）
- 再次右键点击可切换回A组
- 默认为"任意"表示不限制AB比例

【和值范围】
- 设置组合内7个数字之和的范围
- 默认为28-161（最小可能和到最大可能和）
- 可设置任意范围，必须勾选"启用"才能生效

【跨度范围】
- 设置组合内最大数字与最小数字的差值范围
- 默认为6-29（最小可能跨度和最大可能跨度）
- 跨度 = 最大数字 - 最小数字
- 必须勾选"启用"才能生效

【连号段数】
- 可多选，设置组合内连续数字段的数量
- "0组"：没有连号段，所有数字都不连续
- "1组"：有1段连号，如1-2, 3-4-5等（只算1段）
- "2组"：有2段独立的连号，如{1-2,4-5-6}中的1-2和4-5-6
- "3组"：有3段独立的连号，这是7个数字中可能的最大段数
- 可多选，如同时选择"1组"和"2组"
- 默认为"任意"表示不限制

AB分组使用示例：
假设选择了7个数字：3, 5, 7, 11, 19, 23, 29
- 默认全部在A组（橙红色背景+A标签）
- 右键点击 5, 19, 23, 29 将它们移至B组（深紫色背景+B标签）
- 此时 A组: {3, 7, 11}  B组: {5, 19, 23, 29}
- 设置"AB比: 3:4"，则生成的组合必须从A组选3个、从B组选4个
- 共生成 C(3,3) × C(4,4) = 1 个组合: {3, 5, 7, 11, 19, 23, 29}

术语说明：
- 质数：1、2、3、5、7、11、13、17、19、23、29
- 合数：4、6、8、9、10、12、14、15、16、18、20、21、22、24、25、26、27、28、30
- 奇数：不能被2整除的数
- 偶数：能被2整除的数
- 0路：能被3整除的数
- 1路：除以3余1的数
- 2路：除以3余2的数
- 跨度：组合中最大数字减去最小数字的差值
- A组：默认分组，选中数字时自动加入
- B组：通过右键点击将数字从A组切换到B组
"""


# ==================== 主应用类 ====================
class NumberCombinationGenerator:
    def __init__(self, master: tk.Tk):
        self.master = master
        self.master.title("数字组合生成器")
        self.master.geometry(Config.WINDOW_GEOMETRY)
        self.master.minsize(*Config.WINDOW_MIN_SIZE)

        # 设置全局样式
        self._setup_styles()

        # 初始化数据结构
        self.selected_numbers: List[int] = []
        self.group_assignment: Dict[int, str] = {}  # {number: 'A' or 'B'}
        self.listbox_previous_selections: Dict[int, Set[int]] = {}

        # 老板键相关数据
        self.boss_key_enabled = Config.BOSS_KEY_ENABLED
        self.boss_key = Config.BOSS_KEY_DEFAULT
        self.boss_key_fake_mode = Config.BOSS_KEY_FAKE_MODE
        self.boss_key_fake_title = Config.BOSS_KEY_FAKE_TITLE
        self.is_boss_mode_active = False
        self.last_boss_key_time = 0
        self.boss_window = None
        self.original_geometry = None
        self.original_title = None

        # 创建界面
        self._create_widgets()
        self._bind_listbox_events()
        self._bind_boss_key()
        self._update_selected_count()

    def _setup_styles(self) -> None:
        """设置界面样式"""
        style = ttk.Style()
        style.configure('Title.TLabel', font=(Config.FONT_FAMILY, 14, 'bold'))
        style.configure('Section.TLabel', font=(Config.FONT_FAMILY, 12, 'bold'))

    def _create_widgets(self) -> None:
        """创建界面组件"""
        main_frame = ttk.Frame(self.master, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        # 配置网格权重
        self.master.columnconfigure(0, weight=1)
        self.master.rowconfigure(0, weight=1)
        main_frame.columnconfigure(0, weight=1)
        main_frame.columnconfigure(1, weight=1)
        main_frame.rowconfigure(1, weight=1)

        # 标题
        title_label = ttk.Label(main_frame, text="数字组合生成器", style='Title.TLabel')
        title_label.grid(row=0, column=0, columnspan=2, pady=20)

        # 左右面板
        left_panel = ttk.Frame(main_frame)
        left_panel.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(0, 10))
        right_panel = ttk.Frame(main_frame)
        right_panel.grid(row=1, column=1, sticky=(tk.W, tk.E, tk.N, tk.S))

        # 创建各个面板
        self._create_number_selection_panel(left_panel)
        self._create_condition_panel(left_panel)
        self._create_result_panel(right_panel)
        self._create_bottom_buttons(main_frame)

    def _create_number_selection_panel(self, parent: ttk.Frame) -> None:
        """创建数字选择面板"""
        panel = ttk.LabelFrame(parent, text=f"数字选择 ({Config.MIN_SELECTION}-{Config.MAX_SELECTION}个)",
                              style='Section.TLabel')
        panel.pack(fill=tk.BOTH, expand=True, pady=(0, 15))

        self.selected_count_label = ttk.Label(panel, text="已选择: 0 个 (A组: 0个 | B组: 0个)")
        self.selected_count_label.pack(pady=5)

        numbers_frame = ttk.Frame(panel)
        numbers_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

        self.number_buttons: Dict[int, tk.Button] = {}
        for i in range(Config.MIN_NUMBER, Config.MAX_NUMBER + 1):
            btn = tk.Button(
                numbers_frame,
                text=str(i),
                width=6,
                height=2,
                command=partial(self._toggle_number, i),
                relief='raised',
                bd=3,
                cursor='hand2'
            )
            self._apply_button_style(btn, selected=False)

            # 绑定右键事件用于切换AB组
            btn.bind('<Button-3>', partial(self._on_right_click, number=i))
            # macOS右键事件
            btn.bind('<Button-2>', partial(self._on_right_click, number=i))

            row = (i - 1) // 6
            col = (i - 1) % 6
            btn.grid(row=row, column=col, padx=3, pady=3)
            self.number_buttons[i] = btn

        # 添加操作说明面板
        help_frame = ttk.LabelFrame(panel, text="AB分组说明", padding="8")
        help_frame.pack(fill=tk.X, padx=8, pady=(8, 5))

        help_text = ("🖱️ 左键: 选择/取消数字 (默认加入A组)\n"
                     "🖱️ 右键: 切换已选数字的A组⇄B组\n"
                     "📊 提示: 可在\"条件设置-AB比\"中筛选组合比例")
        help_label = ttk.Label(help_frame, text=help_text, foreground='#555555', font=(Config.FONT_FAMILY, 22))
        help_label.pack()

    def _create_condition_panel(self, parent: ttk.Frame) -> None:
        """创建条件设置面板"""
        panel = ttk.LabelFrame(parent, text="条件设置", style='Section.TLabel')
        panel.pack(fill=tk.BOTH, expand=True, pady=(0, 10))

        # 第一行：比例筛选器
        condition_frame = ttk.Frame(panel)
        condition_frame.pack(fill=tk.X, padx=8, pady=8)

        # 使用工厂方法创建筛选器
        col_idx = 0
        self.prime_ratio_listbox = self._create_filter_listbox(
            condition_frame, 'prime_ratio', row=0, col=col_idx)
        col_idx += 2

        self.odd_ratio_listbox = self._create_filter_listbox(
            condition_frame, 'odd_ratio', row=0, col=col_idx, padx_label=(20, 5))
        col_idx += 2

        self.path_ratio_listbox = self._create_filter_listbox(
            condition_frame, 'path_ratio', row=0, col=col_idx, padx_label=(20, 5))
        col_idx += 2

        self.consecutive_listbox = self._create_filter_listbox(
            condition_frame, 'consecutive', row=0, col=col_idx, padx_label=(20, 5))
        col_idx += 2

        self.ab_ratio_listbox = self._create_filter_listbox(
            condition_frame, 'ab_ratio', row=0, col=col_idx, padx_label=(20, 5))

        # 第二行：范围筛选器
        advanced_frame = ttk.Frame(panel)
        advanced_frame.pack(fill=tk.X, padx=8, pady=8)

        # 和值范围
        ttk.Label(advanced_frame, text="和值范围:").grid(row=0, column=0, sticky=tk.W, pady=4)
        ttk.Label(advanced_frame, text="从").grid(row=0, column=1, sticky=tk.W, padx=(5, 2))
        self.sum_min_var = tk.IntVar(value=28)
        self.sum_min_entry = ttk.Entry(advanced_frame, textvariable=self.sum_min_var, width=5)
        self.sum_min_entry.grid(row=0, column=2, padx=2)
        ttk.Label(advanced_frame, text="到").grid(row=0, column=3, sticky=tk.W, padx=(2, 3))
        self.sum_max_var = tk.IntVar(value=161)
        self.sum_max_entry = ttk.Entry(advanced_frame, textvariable=self.sum_max_var, width=5)
        self.sum_max_entry.grid(row=0, column=4, padx=(2, 10))
        self.sum_filter_enabled = tk.BooleanVar(value=False)
        ttk.Checkbutton(advanced_frame, text="启用", variable=self.sum_filter_enabled).grid(
            row=0, column=5, padx=(5, 30))

        # 跨度范围
        ttk.Label(advanced_frame, text="跨度:").grid(row=0, column=6, sticky=tk.W, pady=4)
        ttk.Label(advanced_frame, text="从").grid(row=0, column=7, sticky=tk.W, padx=(5, 2))
        self.span_min_var = tk.IntVar(value=6)
        self.span_min_entry = ttk.Entry(advanced_frame, textvariable=self.span_min_var, width=5)
        self.span_min_entry.grid(row=0, column=8, padx=2)
        ttk.Label(advanced_frame, text="到").grid(row=0, column=9, sticky=tk.W, padx=(2, 3))
        self.span_max_var = tk.IntVar(value=29)
        self.span_max_entry = ttk.Entry(advanced_frame, textvariable=self.span_max_var, width=5)
        self.span_max_entry.grid(row=0, column=10, padx=(2, 15))
        self.span_filter_enabled = tk.BooleanVar(value=False)
        ttk.Checkbutton(advanced_frame, text="启用", variable=self.span_filter_enabled).grid(
            row=0, column=11, padx=(5, 10))

    def _create_filter_listbox(self, parent: ttk.Frame, filter_key: str,
                               row: int, col: int, padx_label: Tuple[int, int] = (0, 5)) -> tk.Listbox:
        """工厂方法：创建筛选器列表框"""
        config = FILTER_CONFIGS[filter_key]

        ttk.Label(parent, text=config['label']).grid(row=row, column=col, sticky=tk.W,
                                                      padx=padx_label, pady=2)

        container = ttk.Frame(parent)
        container.grid(row=row, column=col + 1, padx=8, pady=6)

        listbox = tk.Listbox(container, selectmode=tk.MULTIPLE,
                            width=config['width'], height=config['height'],
                            exportselection=False)

        for option in config['options']:
            listbox.insert(tk.END, option)

        listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        if config.get('scrollbar'):
            scrollbar = ttk.Scrollbar(container, orient=tk.VERTICAL, command=listbox.yview)
            scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
            listbox.configure(yscrollcommand=scrollbar.set)

        listbox.select_set(Config.ANY_OPTION_INDEX)
        return listbox

    def _create_result_panel(self, parent: ttk.Frame) -> None:
        """创建结果展示面板"""
        panel = ttk.LabelFrame(parent, text="结果展示", style='Section.TLabel')
        panel.pack(fill=tk.BOTH, expand=True)

        self.result_text = tk.Text(panel, wrap=tk.NONE, height=20, width=40)
        scrollbar_y = ttk.Scrollbar(panel, orient=tk.VERTICAL, command=self.result_text.yview)
        scrollbar_x = ttk.Scrollbar(panel, orient=tk.HORIZONTAL, command=self.result_text.xview)
        self.result_text.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)

        self.result_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        scrollbar_y.grid(row=0, column=1, sticky=(tk.N, tk.S))
        scrollbar_x.grid(row=1, column=0, sticky=(tk.W, tk.E))

        panel.grid_rowconfigure(0, weight=1)
        panel.grid_columnconfigure(0, weight=1)

        self.result_count_label = ttk.Label(panel, text="组合数量: 0")
        self.result_count_label.grid(row=2, column=0, columnspan=2, pady=5)

    def _create_bottom_buttons(self, parent: ttk.Frame) -> None:
        """创建底部按钮区"""
        button_frame = ttk.Frame(parent)
        button_frame.grid(row=2, column=0, columnspan=2, pady=10)

        buttons = [
            ("生成组合", self._generate_combinations),
            ("清空选择", self._clear_selection),
            ("导出结果", self._export_results),
            ("老板键设置", self._show_boss_key_settings),
            ("帮助说明", self._show_help)
        ]

        for text, command in buttons:
            btn = ttk.Button(button_frame, text=text, command=command)
            btn.pack(side=tk.LEFT, padx=5)
            if text == "导出结果":
                self.export_button = btn

        # 添加老板键状态指示器
        status_text = f"🔧 老板键: {self.boss_key}" if self.boss_key_enabled else "🔧 老板键: 已禁用"
        status_color = 'green' if self.boss_key_enabled else 'gray'
        self.boss_status_label = ttk.Label(button_frame, text=status_text, font=(Config.FONT_FAMILY, 10), foreground=status_color)
        self.boss_status_label.pack(side=tk.RIGHT, padx=(20, 0))

    def _apply_button_style(self, btn: tk.Button, selected: bool, group: Optional[str] = None) -> None:
        """应用按钮样式（支持AB分组显示）"""
        if selected:
            # 获取按钮对应的数字
            number = None
            for num, button in self.number_buttons.items():
                if button == btn:
                    number = num
                    break

            # 根据分组设置不同样式
            if group == 'B':
                btn.configure(
                    bg=Config.GROUP_B_BG,
                    fg=Config.GROUP_B_FG,
                    font=Config.BUTTON_FONT_SELECTED,
                    activebackground=Config.GROUP_B_BG,
                    activeforeground=Config.GROUP_B_FG,
                    relief='raised',
                    bd=3,
                    text=f"{number}\n{Config.GROUP_B_LABEL}" if number else btn.cget('text')
                )
            else:  # group == 'A' or None (default to A)
                btn.configure(
                    bg=Config.SELECTED_BG,
                    fg=Config.SELECTED_FG,
                    font=Config.BUTTON_FONT_SELECTED,
                    activebackground=Config.SELECTED_BG,
                    activeforeground=Config.SELECTED_FG,
                    relief='raised',
                    bd=3,
                    text=f"{number}\n{Config.GROUP_A_LABEL}" if number else btn.cget('text')
                )
        else:
            # 未选中状态
            number = None
            for num, button in self.number_buttons.items():
                if button == btn:
                    number = num
                    break

            btn.configure(
                bg=Config.UNSELECTED_BG,
                fg=Config.UNSELECTED_FG,
                font=Config.BUTTON_FONT_UNSELECTED,
                activebackground=Config.HOVER_BG,
                activeforeground=Config.UNSELECTED_FG,
                relief='raised',
                bd=3,
                text=str(number) if number else btn.cget('text')
            )

    def _toggle_number(self, number: int) -> None:
        """切换数字选择状态（左键）"""
        if number in self.selected_numbers:
            # 取消选择
            self.selected_numbers.remove(number)
            if number in self.group_assignment:
                del self.group_assignment[number]
            self._apply_button_style(self.number_buttons[number], selected=False)
        else:
            # 选择数字
            if len(self.selected_numbers) < Config.MAX_SELECTION:
                self.selected_numbers.append(number)
                self.group_assignment[number] = 'A'  # 默认加入A组
                self._apply_button_style(self.number_buttons[number], selected=True, group='A')
            else:
                messagebox.showwarning("限制", f"最多只能选择{Config.MAX_SELECTION}个数字！")
                return

        self._update_selected_count()

    def _toggle_group(self, number: int) -> None:
        """切换数字的AB组（右键）"""
        if number not in self.selected_numbers:
            return  # 只有已选中的数字才能切换分组

        # 切换分组
        current_group = self.group_assignment.get(number, 'A')
        new_group = 'B' if current_group == 'A' else 'A'
        self.group_assignment[number] = new_group

        # 更新按钮样式
        self._apply_button_style(self.number_buttons[number], selected=True, group=new_group)

        # 更新统计显示
        self._update_selected_count()

    def _on_right_click(self, event: tk.Event, number: int) -> None:
        """处理右键点击事件"""
        self._toggle_group(number)
        return 'break'  # 阻止事件冒泡

    def _update_selected_count(self) -> None:
        """更新选中数字计数显示（包含AB分组统计）"""
        count = len(self.selected_numbers)

        # 统计AB分组
        a_count = sum(1 for num in self.selected_numbers if self.group_assignment.get(num, 'A') == 'A')
        b_count = count - a_count

        # 更新显示文本
        self.selected_count_label.config(text=f"已选择: {count} 个 (A组: {a_count}个 | B组: {b_count}个)")

        # 设置颜色
        color = 'red' if count < Config.MIN_SELECTION or count > Config.MAX_SELECTION else 'black'
        self.selected_count_label.config(foreground=color)

    def _clear_selection(self) -> None:
        """清空所有选择"""
        self.selected_numbers.clear()
        self.group_assignment.clear()  # 清空AB分组
        for btn in self.number_buttons.values():
            self._apply_button_style(btn, selected=False)
        self._update_selected_count()
        self.result_text.delete(1.0, tk.END)
        self.result_count_label.config(text="组合数量: 0")

    def _on_listbox_select(self, event: tk.Event, listbox: tk.Listbox) -> None:
        """处理列表框选择事件：支持在"任意"和具体选项之间切换"""
        current_selection = set(listbox.curselection())
        listbox_id = id(listbox)
        previous_selection = self.listbox_previous_selections.get(listbox_id, set())

        if not current_selection:
            self.listbox_previous_selections[listbox_id] = current_selection
            return

        if Config.ANY_OPTION_INDEX in current_selection and len(current_selection) > 1:
            if Config.ANY_OPTION_INDEX not in previous_selection:
                listbox.selection_clear(0, tk.END)
                listbox.selection_set(Config.ANY_OPTION_INDEX)
            else:
                listbox.selection_clear(Config.ANY_OPTION_INDEX)

        self.listbox_previous_selections[listbox_id] = set(listbox.curselection())

    def _bind_listbox_events(self) -> None:
        """绑定列表框事件"""
        for listbox in [self.prime_ratio_listbox, self.odd_ratio_listbox,
                       self.path_ratio_listbox, self.consecutive_listbox, self.ab_ratio_listbox]:
            listbox.bind('<<ListboxSelect>>', partial(self._on_listbox_select, listbox=listbox))

    def _get_selected_ratios(self, listbox: tk.Listbox) -> str:
        """获取列表框中选中的项目，返回字符串表示"""
        selected_indices = listbox.curselection()
        if not selected_indices:
            return "未选择"

        selected_items = [listbox.get(i) for i in selected_indices]
        if len(selected_items) == 1 and selected_items[0] == "任意":
            return "任意"
        elif len(selected_items) == 1:
            return selected_items[0]
        elif len(selected_items) <= 3:
            return ", ".join(selected_items)
        else:
            return ", ".join(selected_items[:3]) + f" 等{len(selected_items) - 3}项"

    def _generate_combinations(self) -> None:
        """生成符合条件的组合"""
        if not (Config.MIN_SELECTION <= len(self.selected_numbers) <= Config.MAX_SELECTION):
            messagebox.showwarning("警告",
                f"请选择{Config.MIN_SELECTION}-{Config.MAX_SELECTION}个数字！")
            return

        try:
            self._clear_previous_results()

            # 生成所有组合（itertools.combinations已保证顺序，无需再排序）
            combinations = list(itertools.combinations(self.selected_numbers, Config.COMBO_SIZE))

            # 应用筛选条件
            filtered_combinations = [combo for combo in combinations if self._check_conditions(combo)]

            # 显示结果（优化：一次性构建字符串）
            if filtered_combinations:
                filtered_combinations.sort()
                result_lines = [" ".join(f"{num:2d}" for num in combo)
                              for combo in filtered_combinations]
                self.result_text.insert(tk.END, "\n".join(result_lines))

                self.result_count_label.config(
                    text=f"组合数量: {len(filtered_combinations)} (总数: {len(combinations)})")
            else:
                self.result_text.insert(tk.END, "没有符合条件的组合")
                self.result_count_label.config(text="组合数量: 0")

        except ValueError as e:
            self.result_count_label.config(text="组合数量: 0")
            messagebox.showerror("输入错误", f"筛选条件设置有误: {e}")
        except MemoryError:
            self.result_count_label.config(text="组合数量: 0")
            messagebox.showerror("内存不足", "组合数量过大，请减少候选数字")
        except Exception as e:
            self.result_count_label.config(text="组合数量: 0")
            messagebox.showerror("错误", f"生成组合时发生错误: {str(e)}")

    def _clear_previous_results(self) -> None:
        """清空之前的结果和相关状态"""
        self.result_text.delete(1.0, tk.END)
        self.result_count_label.config(text="组合数量: 0")

    def _check_conditions(self, combo: Tuple[int, ...]) -> bool:
        """检查组合是否符合所有条件（责任链模式）"""
        filters: List[Callable] = [
            self._check_prime_condition,
            self._check_odd_condition,
            self._check_path_condition,
            self._check_sum_condition,
            self._check_consecutive_condition,
            self._check_span_condition,
            self._check_ab_ratio_condition
        ]
        return all(filter_func(combo) for filter_func in filters)

    def _check_ratio_condition(self, combo: Tuple[int, ...], listbox: tk.Listbox,
                               counts_calculator: Callable[[Tuple[int, ...]], Tuple[int, ...]]) -> bool:
        """通用比例检查逻辑（提取重复代码）"""
        selected_indices = listbox.curselection()
        if not selected_indices or Config.ANY_OPTION_INDEX in selected_indices:
            return True

        counts = counts_calculator(combo)

        for index in selected_indices:
            ratio_str = listbox.get(index)
            if ratio_str == "任意":
                return True

            expected_counts = tuple(map(int, ratio_str.split(':')))
            if counts == expected_counts:
                return True

        return False

    def _check_prime_condition(self, combo: Tuple[int, ...]) -> bool:
        """检查质合比条件"""
        def calc_counts(combo: Tuple[int, ...]) -> Tuple[int, int]:
            prime_count = sum(1 for num in combo if num in Config.PRIME_NUMBERS)
            return (prime_count, Config.COMBO_SIZE - prime_count)

        return self._check_ratio_condition(combo, self.prime_ratio_listbox, calc_counts)

    def _check_odd_condition(self, combo: Tuple[int, ...]) -> bool:
        """检查奇偶比条件"""
        def calc_counts(combo: Tuple[int, ...]) -> Tuple[int, int]:
            odd_count = sum(1 for num in combo if num % 2 == 1)
            return (odd_count, Config.COMBO_SIZE - odd_count)

        return self._check_ratio_condition(combo, self.odd_ratio_listbox, calc_counts)

    def _check_path_condition(self, combo: Tuple[int, ...]) -> bool:
        """检查012路比条件"""
        def calc_counts(combo: Tuple[int, ...]) -> Tuple[int, int, int]:
            path0 = sum(1 for num in combo if num % 3 == 0)
            path1 = sum(1 for num in combo if num % 3 == 1)
            path2 = sum(1 for num in combo if num % 3 == 2)
            return (path0, path1, path2)

        return self._check_ratio_condition(combo, self.path_ratio_listbox, calc_counts)

    def _check_sum_condition(self, combo: Tuple[int, ...]) -> bool:
        """检查和值范围条件"""
        if not self.sum_filter_enabled.get():
            return True

        sum_value = sum(combo)
        return self.sum_min_var.get() <= sum_value <= self.sum_max_var.get()

    def _check_consecutive_condition(self, combo: Tuple[int, ...]) -> bool:
        """检查连号段数条件"""
        selected_indices = self.consecutive_listbox.curselection()
        if not selected_indices or Config.ANY_OPTION_INDEX in selected_indices:
            return True

        # 优化的连号段计算算法
        consecutive_segments = self._count_consecutive_segments(sorted(combo))

        for index in selected_indices:
            consecutive_str = self.consecutive_listbox.get(index)
            if consecutive_str == "任意":
                return True

            segment_count = int(consecutive_str[0])
            if consecutive_segments == segment_count:
                return True

        return False

    @staticmethod
    def _count_consecutive_segments(sorted_numbers: List[int]) -> int:
        """优化的连号段计算（提取并优化算法）"""
        if not sorted_numbers:
            return 0

        segments = 0
        i = 0
        while i < len(sorted_numbers):
            if i < len(sorted_numbers) - 1 and sorted_numbers[i + 1] == sorted_numbers[i] + 1:
                segments += 1
                while i < len(sorted_numbers) - 1 and sorted_numbers[i + 1] == sorted_numbers[i] + 1:
                    i += 1
            i += 1

        return segments

    def _check_span_condition(self, combo: Tuple[int, ...]) -> bool:
        """检查跨度条件"""
        if not self.span_filter_enabled.get():
            return True

        span_value = max(combo) - min(combo)
        return self.span_min_var.get() <= span_value <= self.span_max_var.get()

    def _check_ab_ratio_condition(self, combo: Tuple[int, ...]) -> bool:
        """检查AB比条件"""
        selected_indices = self.ab_ratio_listbox.curselection()
        if not selected_indices or Config.ANY_OPTION_INDEX in selected_indices:
            return True

        # 统计combo中A组和B组的数量
        a_count = sum(1 for num in combo if self.group_assignment.get(num, 'A') == 'A')
        b_count = len(combo) - a_count

        # 检查是否匹配任一选中的AB比
        for index in selected_indices:
            ratio_str = self.ab_ratio_listbox.get(index)
            if ratio_str == "任意":
                return True

            expected_a, expected_b = map(int, ratio_str.split(':'))
            if a_count == expected_a and b_count == expected_b:
                return True

        return False

    def _get_filter_summary(self) -> Dict[str, str]:
        """获取筛选条件摘要（提取重复代码）"""
        # 获取AB组的数字列表
        a_numbers = [num for num in sorted(self.selected_numbers)
                     if self.group_assignment.get(num, 'A') == 'A']
        b_numbers = [num for num in sorted(self.selected_numbers)
                     if self.group_assignment.get(num, 'A') == 'B']

        ab_info = f"A组{a_numbers} B组{b_numbers}" if a_numbers or b_numbers else "未分组"

        return {
            'prime_ratios': self._get_selected_ratios(self.prime_ratio_listbox),
            'odd_ratios': self._get_selected_ratios(self.odd_ratio_listbox),
            'path_ratios': self._get_selected_ratios(self.path_ratio_listbox),
            'consecutive_ratios': self._get_selected_ratios(self.consecutive_listbox),
            'ab_ratios': self._get_selected_ratios(self.ab_ratio_listbox),
            'ab_group_info': ab_info,
            'sum_condition': (f"和值范围: {self.sum_min_var.get()}-{self.sum_max_var.get()}"
                             if self.sum_filter_enabled.get() else "和值范围: 任意"),
            'span_condition': (f"跨度范围: {self.span_min_var.get()}-{self.span_max_var.get()}"
                              if self.span_filter_enabled.get() else "跨度范围: 任意")
        }

    def _export_results(self) -> None:
        """导出结果"""
        content = self.result_text.get(1.0, tk.END).strip()
        if not content:
            messagebox.showwarning("警告", "没有可导出的结果！")
            return

        file_types = [("文本文件", "*.txt"), ("CSV文件", "*.csv"), ("所有文件", "*.*")]
        filename = filedialog.asksaveasfilename(
            defaultextension=".txt",
            filetypes=file_types,
            title="导出结果",
            initialfile=f"数字组合结果_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
        )

        if filename:
            try:
                if filename.endswith('.csv'):
                    self._export_to_csv(filename, content)
                else:
                    self._export_to_txt(filename, content)
                messagebox.showinfo("成功", f"结果已导出到: {filename}")
            except IOError as e:
                messagebox.showerror("IO错误", f"文件写入失败: {e}")
            except Exception as e:
                messagebox.showerror("错误", f"导出失败: {str(e)}")

    def _export_to_txt(self, filename: str, content: str) -> None:
        """导出为文本文件"""
        filter_summary = self._get_filter_summary()

        with open(filename, 'w', encoding='utf-8') as f:
            f.write("数字组合生成器结果\n")
            f.write(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
            f.write(f"候选数字: {sorted(self.selected_numbers)}\n")
            f.write(f"AB分组: {filter_summary['ab_group_info']}\n")
            f.write(f"条件设置: 质合比={filter_summary['prime_ratios']}, "
                   f"奇偶比={filter_summary['odd_ratios']}, "
                   f"012路比={filter_summary['path_ratios']}, "
                   f"{filter_summary['sum_condition']}, "
                   f"连号段数={filter_summary['consecutive_ratios']}, "
                   f"{filter_summary['span_condition']}, "
                   f"AB比={filter_summary['ab_ratios']}\n")
            f.write(f"{'=' * 50}\n\n")
            f.write(content)

    def _export_to_csv(self, filename: str, content: str) -> None:
        """导出为CSV文件"""
        filter_summary = self._get_filter_summary()
        lines = content.strip().split('\n')

        with open(filename, 'w', newline='', encoding='utf-8-sig') as csvfile:
            writer = csv.writer(csvfile)
            writer.writerow(['数字组合生成器结果'])
            writer.writerow(['生成时间', datetime.now().strftime('%Y-%m-%d %H:%M:%S')])
            writer.writerow(['候选数字', str(sorted(self.selected_numbers))])
            writer.writerow(['AB分组', filter_summary['ab_group_info']])
            writer.writerow(['条件设置',
                           f"质合比={filter_summary['prime_ratios']}, "
                           f"奇偶比={filter_summary['odd_ratios']}, "
                           f"012路比={filter_summary['path_ratios']}, "
                           f"{filter_summary['sum_condition']}, "
                           f"连号段数={filter_summary['consecutive_ratios']}, "
                           f"{filter_summary['span_condition']}, "
                           f"AB比={filter_summary['ab_ratios']}"])
            writer.writerow([])
            writer.writerow(['序号', '数字1', '数字2', '数字3', '数字4', '数字5', '数字6', '数字7'])

            for i, line in enumerate(lines, 1):
                numbers = line.split()
                writer.writerow([i] + numbers)

    def _show_help(self) -> None:
        """显示帮助信息"""
        help_window = tk.Toplevel(self.master)
        help_window.title("帮助说明")
        help_window.geometry("600x500")

        text_widget = tk.Text(help_window, wrap=tk.WORD, padx=20, pady=20)
        text_widget.pack(fill=tk.BOTH, expand=True)
        text_widget.insert(tk.END, HELP_TEXT)
        text_widget.config(state=tk.DISABLED)

        scrollbar = ttk.Scrollbar(help_window, command=text_widget.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        text_widget.config(yscrollcommand=scrollbar.set)

    def _bind_boss_key(self) -> None:
        """绑定老板键"""
        if self.boss_key_enabled:
            # 绑定老板键到主窗口
            self.master.bind(f'<{self.boss_key}>', self._on_boss_key_press)
            self.master.bind(f'<KeyPress-{self.boss_key}>', self._on_boss_key_press)

            # 绑定到所有子窗口
            self.master.bind_all(f'<{self.boss_key}>', self._on_boss_key_press)
            self.master.bind_all(f'<KeyPress-{self.boss_key}>', self._on_boss_key_press)

    def _on_boss_key_press(self, event: tk.Event) -> None:
        """处理老板键按下事件"""
        if not self.boss_key_enabled:
            return

        current_time = event.time
        time_diff = current_time - self.last_boss_key_time

        # 检测双击（500ms内）
        if time_diff < Config.BOSS_KEY_DOUBLE_CLICK_THRESHOLD:
            if self.is_boss_mode_active:
                # 在老板模式下，双击退出
                self._toggle_boss_mode()
            else:
                # 在正常模式下，双击进入
                self._toggle_boss_mode()
        else:
            # 第一次按下时显示小提示（仅在正常模式下）
            if not self.is_boss_mode_active:
                self._show_boss_key_hint()

        self.last_boss_key_time = current_time
        return 'break'  # 阻止事件传播

    def _show_boss_key_hint(self) -> None:
        """显示老板键提示"""
        if not self.is_boss_mode_active:
            # 在界面角落显示一个小提示
            hint_window = tk.Toplevel(self.master)
            hint_window.wm_overrideredirect(True)  # 无边框
            hint_window.geometry("+10+10")

            hint_label = tk.Label(
                hint_window,
                text=f"再次按{self.boss_key}激活老板键",
                bg='#FFFF00',
                fg='#000000',
                font=(Config.FONT_FAMILY, 10),
                padx=10,
                pady=5
            )
            hint_label.pack()

            # 500ms后自动消失
            hint_window.after(500, hint_window.destroy)

    def _toggle_boss_mode(self) -> None:
        """切换老板模式"""
        if not self.is_boss_mode_active:
            # 进入老板模式
            self._enter_boss_mode()
        else:
            # 退出老板模式
            self._exit_boss_mode()

    def _enter_boss_mode(self) -> None:
        """进入老板模式"""
        # 保存当前状态
        self.original_geometry = self.master.geometry()
        self.original_title = self.master.title()

        # 隐藏主窗口
        self.master.withdraw()

        # 显示伪装界面
        self._create_fake_window()

        self.is_boss_mode_active = True

        # 更新状态指示器
        if hasattr(self, 'boss_status_label'):
            self.boss_status_label.config(text="📄 老板键激活", foreground='red')

    def _exit_boss_mode(self) -> None:
        """退出老板模式"""
        # 恢复主窗口
        self.master.deiconify()
        if self.original_geometry:
            self.master.geometry(self.original_geometry)
        if self.original_title:
            self.master.title(self.original_title)

        # 关闭伪装窗口
        if self.boss_window:
            self.boss_window.destroy()
            self.boss_window = None

        self.is_boss_mode_active = False

        # 更新状态指示器
        if hasattr(self, 'boss_status_label'):
            self.boss_status_label.config(text=f"🔧 老板键: {self.boss_key}", foreground='green')

    def _create_fake_window(self) -> None:
        """创建伪装窗口"""
        self.boss_window = tk.Toplevel(self.master)
        self.boss_window.title(self.boss_key_fake_title)
        self.boss_window.geometry("800x600")
        self.boss_window.minsize(600, 400)

        # 绑定老板键到伪装窗口
        self.boss_window.bind(f'<{self.boss_key}>', self._on_boss_key_press)
        self.boss_window.bind(f'<KeyPress-{self.boss_key}>', self._on_boss_key_press)

        if self.boss_key_fake_mode == "document":
            self._create_fake_document()
        else:
            self._create_fake_terminal()

    def _create_fake_document(self) -> None:
        """创建伪装文档界面"""
        # 主框架
        main_frame = ttk.Frame(self.boss_window)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 标题
        title_label = tk.Label(
            main_frame,
            text="项目进度报告",
            font=(Config.FONT_FAMILY, 16, 'bold'),
            anchor='w'
        )
        title_label.pack(fill=tk.X, pady=(0, 20))

        # 分隔线
        separator = ttk.Separator(main_frame, orient='horizontal')
        separator.pack(fill=tk.X, pady=(0, 20))

        # 内容区域
        content_frame = ttk.Frame(main_frame)
        content_frame.pack(fill=tk.BOTH, expand=True)

        # 任务列表
        tasks = [
            "✓ 完成了数据分析部分",
            "✓ 正在处理用户反馈",
            "○ 下一步: 优化算法性能",
            "○ 待办: 更新用户界面",
            "○ 待办: 编写技术文档"
        ]

        for task in tasks:
            task_label = tk.Label(
                content_frame,
                text=task,
                font=(Config.FONT_FAMILY, 12),
                anchor='w'
            )
            task_label.pack(fill=tk.X, pady=5)

        # 进度条区域
        progress_frame = ttk.Frame(main_frame)
        progress_frame.pack(fill=tk.X, pady=20)

        progress_label = tk.Label(
            progress_frame,
            text="整体进度:",
            font=(Config.FONT_FAMILY, 11),
            anchor='w'
        )
        progress_label.pack(fill=tk.X, pady=(0, 5))

        # 简单的进度条显示
        progress_bar_frame = tk.Frame(progress_frame, bg='#E0E0E0', height=20)
        progress_bar_frame.pack(fill=tk.X)
        progress_bar_frame.pack_propagate(False)

        progress_fill = tk.Frame(progress_bar_frame, bg='#4CAF50', height=20)
        progress_fill.place(x=0, y=0, relwidth=0.8, relheight=1)

        progress_text = tk.Label(
            progress_frame,
            text="80% 完成",
            font=(Config.FONT_FAMILY, 10),
            anchor='w'
        )
        progress_text.pack(fill=tk.X, pady=(5, 0))

    def _create_fake_terminal(self) -> None:
        """创建伪装命令行界面"""
        # 终端样式的文本区域
        terminal_frame = tk.Frame(self.boss_window, bg='black')
        terminal_frame.pack(fill=tk.BOTH, expand=True)

        terminal_text = tk.Text(
            terminal_frame,
            bg='black',
            fg='white',
            font=('Consolas', 11),
            wrap=tk.WORD,
            insertbackground='white'
        )
        terminal_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

        # 预设的命令行内容
        terminal_content = """Microsoft Windows [版本 10.0.19045.2364]
(c) Microsoft Corporation。保留所有权利。

C:\\Users\\Administrator>dir
 驱动器 C 中的卷是 Windows
 卷的序列号是 XXXX-XXXX

 C:\\Users\\Administrator 的目录

2024/10/25  14:30    <DIR>          .
2024/10/25  14:30    <DIR>          ..
2024/10/25  14:28    <DIR>          Desktop
2024/10/25  14:25    <DIR>          Documents
2024/10/25  14:22    <DIR>          Downloads
2024/10/25  14:20               1,234 report.txt
2024/10/25  14:15               5,678 data.xlsx
               2 个文件          6,912 字节
               4 个目录 100,000,000,000 可用字节

C:\\Users\\Administrator>_
"""

        terminal_text.insert(tk.END, terminal_content)
        terminal_text.config(state=tk.DISABLED)

    def _update_boss_key_config(self, key: str, fake_mode: str, fake_title: str) -> None:
        """更新老板键配置"""
        # 先解绑旧的按键
        if self.boss_key_enabled:
            self.master.unbind_all(f'<{self.boss_key}>')
            self.master.unbind_all(f'<KeyPress-{self.boss_key}>')
            self.master.unbind(f'<{self.boss_key}>')
            self.master.unbind(f'<KeyPress-{self.boss_key}>')

        # 更新配置
        self.boss_key = key
        self.boss_key_fake_mode = fake_mode
        self.boss_key_fake_title = fake_title

        # 重新绑定
        self._bind_boss_key()

        # 更新状态指示器
        if hasattr(self, 'boss_status_label'):
            self.boss_status_label.config(text=f"🔧 老板键: {self.boss_key}", foreground='green')

    def _show_boss_key_settings(self) -> None:
        """显示老板键设置窗口"""
        settings_window = tk.Toplevel(self.master)
        settings_window.title("老板键设置")
        settings_window.geometry("450x400")
        settings_window.resizable(False, False)

        # 居中显示
        settings_window.transient(self.master)
        settings_window.grab_set()

        # 主框架
        main_frame = ttk.Frame(settings_window, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 标题
        title_label = ttk.Label(main_frame, text="老板键设置", font=(Config.FONT_FAMILY, 14, 'bold'))
        title_label.grid(row=0, column=0, columnspan=2, pady=(0, 20))

        # 启用老板键
        enable_var = tk.BooleanVar(value=self.boss_key_enabled)
        enable_check = ttk.Checkbutton(main_frame, text="启用老板键功能", variable=enable_var)
        enable_check.grid(row=1, column=0, columnspan=2, sticky=tk.W, pady=10)

        # 快捷键选择
        ttk.Label(main_frame, text="快捷键选择:").grid(row=2, column=0, sticky=tk.W, pady=(10, 5))
        key_var = tk.StringVar(value=self.boss_key)
        key_frame = ttk.Frame(main_frame)
        key_frame.grid(row=2, column=1, sticky=tk.W, pady=(10, 5))

        keys = ['F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'Pause', 'Insert', '~']
        key_combo = ttk.Combobox(key_frame, textvariable=key_var, values=keys, width=8, state='readonly')
        key_combo.pack(side=tk.LEFT)

        # 伪装模式选择
        ttk.Label(main_frame, text="伪装界面:").grid(row=3, column=0, sticky=tk.W, pady=(10, 5))
        mode_var = tk.StringVar(value=self.boss_key_fake_mode)
        mode_frame = ttk.Frame(main_frame)
        mode_frame.grid(row=3, column=1, sticky=tk.W, pady=(10, 5))

        modes = [('工作文档', 'document'), ('命令行', 'terminal')]
        for text, value in modes:
            rb = ttk.Radiobutton(mode_frame, text=text, variable=mode_var, value=value)
            rb.pack(side=tk.LEFT, padx=(0, 10))

        # 伪装窗口标题
        ttk.Label(main_frame, text="窗口标题:").grid(row=4, column=0, sticky=tk.W, pady=(10, 5))
        title_var = tk.StringVar(value=self.boss_key_fake_title)
        title_entry = ttk.Entry(main_frame, textvariable=title_var, width=25)
        title_entry.grid(row=4, column=1, sticky=tk.W, pady=(10, 5))

        # 使用说明
        separator = ttk.Separator(main_frame, orient='horizontal')
        separator.grid(row=5, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=20)

        instructions_frame = ttk.LabelFrame(main_frame, text="使用说明", padding="10")
        instructions_frame.grid(row=6, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 20))

        instructions = """1. 快速双击选定的按键激活老板键
2. 激活后程序界面会隐藏，显示伪装界面
3. 再次双击相同按键恢复原界面
4. 老板键在所有窗口中都能响应

提示：建议选择不常用的按键（如F12）以避免误触"""

        instructions_label = ttk.Label(instructions_frame, text=instructions, justify=tk.LEFT,
                                     font=(Config.FONT_FAMILY, 9))
        instructions_label.pack()

        # 按钮区域
        button_frame = ttk.Frame(main_frame)
        button_frame.grid(row=7, column=0, columnspan=2, pady=20)

        def apply_settings():
            """应用设置"""
            new_key = key_var.get()
            new_mode = mode_var.get()
            new_title = title_var.get()
            new_enabled = enable_var.get()

            # 验证标题
            if not new_title.strip():
                messagebox.showwarning("警告", "窗口标题不能为空！")
                return

            # 更新设置
            self.boss_key_enabled = new_enabled
            if new_enabled:
                self._update_boss_key_config(new_key, new_mode, new_title)
            else:
                # 禁用老板键
                self.master.unbind_all(f'<{self.boss_key}>')
                self.master.unbind_all(f'<KeyPress-{self.boss_key}>')
                self.master.unbind(f'<{self.boss_key}>')
                self.master.unbind(f'<KeyPress-{self.boss_key}>')
                if hasattr(self, 'boss_status_label'):
                    self.boss_status_label.config(text="🔧 老板键: 已禁用", foreground='gray')

            messagebox.showinfo("成功", "老板键设置已保存！")
            settings_window.destroy()

        def test_boss_key():
            """测试老板键"""
            messagebox.showinfo("测试", f"请快速双击 {key_var.get()} 键测试老板键功能。\n\n"
                                     f"第一次按下会显示提示，\n"
                                     f"快速双击即可激活老板键模式。")

        ttk.Button(button_frame, text="应用设置", command=apply_settings).pack(side=tk.LEFT, padx=(0, 10))
        ttk.Button(button_frame, text="测试按键", command=test_boss_key).pack(side=tk.LEFT, padx=(0, 10))
        ttk.Button(button_frame, text="取消", command=settings_window.destroy).pack(side=tk.LEFT)

        # 更新启用状态的响应
        def on_enable_change():
            """启用状态改变时的响应"""
            enabled = enable_var.get()
            key_combo.config(state='normal' if enabled else 'disabled')
            for rb in mode_frame.winfo_children():
                if isinstance(rb, ttk.Radiobutton):
                    rb.config(state='normal' if enabled else 'disabled')
            title_entry.config(state='normal' if enabled else 'disabled')

        enable_var.trace('w', lambda *args: on_enable_change())


def main() -> None:
    """主函数"""
    root = tk.Tk()
    app = NumberCombinationGenerator(root)
    root.mainloop()


if __name__ == "__main__":
    main()
